package crossover;

import java.util.LinkedList;
import java.util.List;

import util.GAConfig;
import util.Log;

import GA.*;
import Operations.Operation;
public abstract class CrossoverStrategy implements Crossover{
	protected abstract boolean getCrossoverFlag();
	protected abstract int[] getCrossoverPoints(int individual1_Size,int individual2_Size);
	
	
	public Chromosome[] crossOver(Chromosome individual1, Chromosome individual2) {
	//	System.out.println("crossoverPoints "+ individual1.getSize()+ " , "+individual2.getSize()); 
		Chromosome offspring1 =(Chromosome) individual1.clone();
		Chromosome offspring2 = (Chromosome) individual2.clone();

		if(this.getCrossoverFlag() == false)
			return new Chromosome[] { offspring1, offspring2 };
	
		int[] crossoverPoints =this.getCrossoverPoints(individual1.getSize(),individual2.getSize());
		//System.out.println("crossoverPoints "+ crossoverPoints[0]+ " , "+crossoverPoints[1]); 
		if(GAConfig.generateNewPopulation)Log.log("crossoverPoints "+ crossoverPoints[0]+ " , "+crossoverPoints[1]+"\n"); 
		if(crossoverPoints == null)
			throw new RuntimeException("The overriden method 'getCrossoverPoints()' returned a null value");
		//Perform the cross over
		for(int i = 0; i < crossoverPoints.length; i++) {
			
			if(i== 0){
				//offspring2
				List<Operation>  rep= new LinkedList<Operation>();
				List<Operation>  ops=individual2.getTest();
				 //clone
				rep.addAll(ops.subList(0, crossoverPoints[i+1]));
				 ops=individual1.getTest();
				 //append
				rep.addAll(ops.subList(crossoverPoints[i], ops.size()));
				offspring2.setTest(rep);
	//			System.out.println("offspring2:"+offspring2);
			}
			else{
				//offspring1
				List<Operation>  rep= new LinkedList<Operation>();
				 //clone
				List<Operation>  ops=individual1.getTest();
				rep.addAll(ops.subList(0, crossoverPoints[i-1]));
				 ops=individual2.getTest();
					//append
				rep.addAll(ops.subList(crossoverPoints[i], ops.size()));

				offspring1.setTest(rep);
			//	System.out.println("offspring1:"+offspring1);
			}


		}
		return new Chromosome[] { offspring1, offspring2 };
		
	}
}
